home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
gawk
/
gawk213b.zoo
/
test
/
awf
/
pass3
< prev
next >
Wrap
Text File
|
1990-10-21
|
10KB
|
333 lines
# third pass: setting lines and pages
# The input language of this pass is basically <width, word> pairs, where
# "word" may have imbedded strangeness (backspaces, etc.) for font changes
# and special characters. Zero width is not special. A third field may
# appear to indicate that this is a fragment of a word that can be
# hyphenated; the third field is the width of the hyphen that would have
# to be added if the line broke after this fragment.
# Negative widths denote special operations. -3 is an error message, the
# second field being the message. -1 and -2 are control messages to this
# pass, the difference being whether a break is implied or not. The second
# field is a message type string; more fields may appear as arguments. The
# semantics of control messages are often -- but not always! -- similar to
# those of troff commands. For example, "linelen" is .ll, but "center" is
# not semantically equivalent to .ce -- it is related but more primitive.
BEGIN {
# input and output details
FS = "\t"
nobreak = -1
dobreak = -2
message = -3
errs = "awf.errs" # default only, normally changed by "errsto"
# page setup -- some are defaults only, normally altered by pass 2
nextlineno = 1
thispageno = 1
topmargin = 5
botmargin = 5
ind = 0 # current indent
tmpind = 0
pageoffset = "" # string to emit at start of each line
nospacemode = 1
hdrs["CH"] = "- % -"
nop = split("LH,CH,RH,LF,CF,RF", hdrnames, ",")
fph = 0 # print header on first page?
fill = 1
adj = "both"
pagelen = 66
linelen = 78
# line-builder setup
line = "" # line so far, without padding
paddable = "" # x means corresp. char in "line" is paddable
thislinelen = -1 # -1 means nothing there
cont = " " # thing to append to continue line
contlen = 1
eol = "" # thing to append to break line
eollen = 0
padfrom = "R" # "L" or "R", alternating for river avoidance
# many spaces, so we can use substr to get any number we need
sps = " "
sps = sps sps sps sps sps sps sps sps sps sps
}
{
# process word, if any, causing a break if appropriate
if ($1 >= 0 && thislinelen < 0) { # word, and first on line
line = $2
paddable = substr(sps, 1, length($2))
thislinelen = $1
} else if ($1 >= 0 && thislinelen+contlen+$1+$3 <= linelen-ind-tmpind) {
# word, and it fits on line
line = line cont $2
if (cont == " ")
paddable = paddable "x"
else
paddable = paddable substr(sps, 1, length(cont))
paddable = paddable substr(sps, 1, length($2))
thislinelen += contlen + $1
} else if ($1 == nobreak || $1 == message)
nop = 0 # no attention (i.e. break) needed here
else if ($1 == dobreak && $2 == "need" && \
nextlineno + $3 < pagelen + 1 - botmargin)
nop = 0 # enough space is available, no action needed
else if ($1 == dobreak && $2 == "toindent" && \
ind + tmpind + thislinelen < ind) {
# move to indent position within line; there is room
n = ind - (ind + tmpind + thislinelen)
line = line substr(sps, 1, n)
# nothing before this is paddable
paddable = substr(sps, 1, length(line))
thislinelen += n
# prevent padding immediately after this point
cont = ""
contlen = 0
} else if (thislinelen >= 0 || ($1 == dobreak && $2 == "need")) {
# must emit output, either due to break or "need"
# if at top of page, header
if (nextlineno == 1) {
for (i = int((topmargin-1)/2); i > 0; i--) {
print ""
nextlineno++
}
for (hno in hdrnames) {
h = hdrnames[hno]
if (hdrs[h] ~ /%/) {
n = split(hdrs[h], t, "%")
thispagehdrs[h] = t[1] thispageno t[2]
} else
thispagehdrs[h] = hdrs[h]
}
if (fph || thispageno > 1) {
lh = thispagehdrs["LH"]
ch = thispagehdrs["CH"]
rh = thispagehdrs["RH"]
lsp = int((linelen - length(lh ch rh)) / 2)
rsp = linelen - length(lh ch rh) - lsp
print pageoffset lh substr(sps, 1, lsp) ch substr(sps, 1, rsp) rh
} else
print ""
nextlineno++
while (nextlineno <= topmargin) {
print ""
nextlineno++
}
}
# the current line
# first, add a trailing hyphen if any
line = line eol
paddable = paddable substr(sps, 1, length(eol))
thislinelen += eollen
# trim trailing spaces if any
while (line ~ / $/) {
line = substr(line, 1, length(line)-1)
paddable = substr(paddable, 1, length(line))
thislinelen--
}
# print it in a suitable way
if (line == "") # empty always prints as nothing
print ""
else if ($1 < 0 && $2 == "center") {
# center it
hsp = int((linelen - thislinelen) / 2)
if (hsp < 0)
hsp = 0
print pageoffset substr(sps, 1, ind+tmpind+hsp) line
} else if (adj == "left" || (adj == "both" && \
($1 < 0 || index(paddable, "x") == 0)))
# no right-margin adjustment (disabled, inappropriate
# (line ended by break), or impossible)
print pageoffset substr(sps, 1, ind+tmpind) line
else if (adj == "both") {
# hard case -- adjust right margin
# sanity check
if (length(paddable) != length(line)) # aieeeee
printf "awf: %f != %f!\n", length(paddable), \
length(line) >errs
# compute parameters
textlen = linelen - (ind+tmpind)
mustadd = textlen - thislinelen
npad = 0 # number of paddable spaces
for (tmp = paddable; (i = index(tmp, "x")) > 0; \
tmp = substr(tmp, i+1))
npad++
addatall = int(mustadd/npad) # all grow this much
spall = substr(sps, 1, addatall)
nmore = mustadd - addatall*npad # this many grow more
# build padded output text
out = substr(sps, 1, ind+tmpind)
padno = 0
while ((i = index(paddable, "x")) > 0) {
out = out substr(line, 1, i)
padno++
out = out spall
if (padfrom == "L") {
if (padno <= nmore)
out = out " "
} else {
if (padno > npad-nmore)
out = out " "
}
line = substr(line, i+1)
paddable = substr(paddable, i+1)
}
# print it, plus remnant not processed by loop
print pageoffset out line
# tidy up
if (padfrom == "L")
padfrom = "R"
else
padfrom = "L"
}
# tidy up after output line
nextlineno++
line = ""
paddable = ""
thislinelen = -1
tmpind = 0
nospacemode = 0
# if we broke from a "need", go to bottom of page
if ($1 == dobreak && $2 == "need")
while (nextlineno < pagelen + 1 - botmargin) {
print ""
nextlineno++
}
# footer, if at bottom of page
if (nextlineno >= pagelen + 1 - botmargin) {
for (i = int((botmargin-1)/2); i > 0; i--) {
print ""
nextlineno++
}
# header code prepared thispagehdrs
lf = thispagehdrs["LF"]
cf = thispagehdrs["CF"]
rf = thispagehdrs["RF"]
lsp = int((linelen - length(lf cf rf)) / 2)
rsp = linelen - length(lf cf rf) - lsp
print pageoffset lf substr(sps, 1, lsp) cf substr(sps, 1, rsp) rf
nextlineno++
while (nextlineno <= pagelen) {
print ""
nextlineno++
}
nextlineno = 1
thispageno++
# after page break, should not space unnecessarily,
# and should pad first line from right
nospacemode = 1
padfrom = "R"
}
# we are finally done with emitting output
# pick up input word, if any
if ($1 >= 0) {
line = $2
paddable = substr(sps, 1, length($2))
thislinelen = $1
}
}
# if we broke, next line should pad from right
if ($1 == dobreak)
padfrom = "R"
# cleanup and post-break command processing
if ($1 >= 0 || $2 == "nohyphen") {
# reset hyphenation trickery after each word (fragment)
cont = " "
contlen = 1
eol = ""
eollen = 0
} else if ($2 == "need" || $2 == "toindent")
nop = 0 # dealt with above
else if ($2 == "flush" || $2 == "center")
nop = 0 # exist only to cause break
else if ($1 == message)
print "awf: " $2 >errs
else if ($2 == "gap") {
# gap between last word and next one should be >= $3
if (thislinelen >= 0) {
line = line substr(sps, 1, $3-1)
paddable = paddable substr(sps, 1, $3-1)
thislinelen += $3-1
}
} else if ($2 == "tabto") {
# move to tab stop at $3
if (thislinelen < 0)
thislinelen = 0 # make line exist
n = $3 - thislinelen
if (n > 0) { # must emit some space
line = line substr(sps, 1, n)
# nothing before a tab is paddable
paddable = substr(sps,